<!DOCTYPE HTML>
<html lang="en" class="light" dir="ltr">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>内联汇编 - The Rust Reference</title>


        <!-- Custom HTML head -->
        
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff">

        <link rel="icon" href="favicon.svg">
        <link rel="shortcut icon" href="favicon.png">
        <link rel="stylesheet" href="css/variables.css">
        <link rel="stylesheet" href="css/general.css">
        <link rel="stylesheet" href="css/chrome.css">
        <link rel="stylesheet" href="css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="highlight.css">
        <link rel="stylesheet" href="tomorrow-night.css">
        <link rel="stylesheet" href="ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        <link rel="stylesheet" href="theme/reference.css">

    </head>
    <body class="sidebar-visible no-js">
    <div id="body-container">
        <!-- Provide site root to javascript -->
        <script>
            var path_to_root = "";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('light')
            html.classList.add(theme);
            var body = document.querySelector('body');
            body.classList.remove('no-js')
            body.classList.add('js');
        </script>

        <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            var body = document.querySelector('body');
            var sidebar = null;
            var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
            }
            sidebar_toggle.checked = sidebar === 'visible';
            body.classList.remove('sidebar-visible');
            body.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded affix "><a href="翻译说明.html">翻译说明</a></li><li class="chapter-item expanded affix "><a href="introduction.html">介绍</a></li><li class="chapter-item expanded "><a href="notation.html"><strong aria-hidden="true">1.</strong> 表义符</a></li><li class="chapter-item expanded "><a href="lexical-structure.html"><strong aria-hidden="true">2.</strong> 词法结构</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="input-format.html"><strong aria-hidden="true">2.1.</strong> 输入格式</a></li><li class="chapter-item expanded "><a href="keywords.html"><strong aria-hidden="true">2.2.</strong> 关键字</a></li><li class="chapter-item expanded "><a href="identifiers.html"><strong aria-hidden="true">2.3.</strong> 标识符</a></li><li class="chapter-item expanded "><a href="comments.html"><strong aria-hidden="true">2.4.</strong> 注释</a></li><li class="chapter-item expanded "><a href="whitespace.html"><strong aria-hidden="true">2.5.</strong> 空白符</a></li><li class="chapter-item expanded "><a href="tokens.html"><strong aria-hidden="true">2.6.</strong> token</a></li></ol></li><li class="chapter-item expanded "><a href="macros.html"><strong aria-hidden="true">3.</strong> 宏</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="macros-by-example.html"><strong aria-hidden="true">3.1.</strong> 声明宏</a></li><li class="chapter-item expanded "><a href="procedural-macros.html"><strong aria-hidden="true">3.2.</strong> 过程宏</a></li></ol></li><li class="chapter-item expanded "><a href="crates-and-source-files.html"><strong aria-hidden="true">4.</strong> crate 和源文件</a></li><li class="chapter-item expanded "><a href="conditional-compilation.html"><strong aria-hidden="true">5.</strong> 条件编译</a></li><li class="chapter-item expanded "><a href="items.html"><strong aria-hidden="true">6.</strong> 程序项</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="items/modules.html"><strong aria-hidden="true">6.1.</strong> 模块</a></li><li class="chapter-item expanded "><a href="items/extern-crates.html"><strong aria-hidden="true">6.2.</strong> 外部crate</a></li><li class="chapter-item expanded "><a href="items/use-declarations.html"><strong aria-hidden="true">6.3.</strong> use声明</a></li><li class="chapter-item expanded "><a href="items/functions.html"><strong aria-hidden="true">6.4.</strong> 函数</a></li><li class="chapter-item expanded "><a href="items/type-aliases.html"><strong aria-hidden="true">6.5.</strong> 类型别名</a></li><li class="chapter-item expanded "><a href="items/structs.html"><strong aria-hidden="true">6.6.</strong> 结构体</a></li><li class="chapter-item expanded "><a href="items/enumerations.html"><strong aria-hidden="true">6.7.</strong> 枚举</a></li><li class="chapter-item expanded "><a href="items/unions.html"><strong aria-hidden="true">6.8.</strong> 联合体</a></li><li class="chapter-item expanded "><a href="items/constant-items.html"><strong aria-hidden="true">6.9.</strong> 常量项</a></li><li class="chapter-item expanded "><a href="items/static-items.html"><strong aria-hidden="true">6.10.</strong> 静态项</a></li><li class="chapter-item expanded "><a href="items/traits.html"><strong aria-hidden="true">6.11.</strong> trait</a></li><li class="chapter-item expanded "><a href="items/implementations.html"><strong aria-hidden="true">6.12.</strong> 实现</a></li><li class="chapter-item expanded "><a href="items/external-blocks.html"><strong aria-hidden="true">6.13.</strong> 外部块</a></li><li class="chapter-item expanded "><a href="items/generics.html"><strong aria-hidden="true">6.14.</strong> 泛型参数</a></li><li class="chapter-item expanded "><a href="items/associated-items.html"><strong aria-hidden="true">6.15.</strong> 关联程序项</a></li></ol></li><li class="chapter-item expanded "><a href="attributes.html"><strong aria-hidden="true">7.</strong> 属性</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="attributes/testing.html"><strong aria-hidden="true">7.1.</strong> 测试</a></li><li class="chapter-item expanded "><a href="attributes/derive.html"><strong aria-hidden="true">7.2.</strong> 派生</a></li><li class="chapter-item expanded "><a href="attributes/diagnostics.html"><strong aria-hidden="true">7.3.</strong> 诊断</a></li><li class="chapter-item expanded "><a href="attributes/codegen.html"><strong aria-hidden="true">7.4.</strong> 代码生成</a></li><li class="chapter-item expanded "><a href="attributes/limits.html"><strong aria-hidden="true">7.5.</strong> 极限值设置</a></li><li class="chapter-item expanded "><a href="attributes/type_system.html"><strong aria-hidden="true">7.6.</strong> 类型系统</a></li><li class="chapter-item expanded "><a href="attributes/debugger.html"><strong aria-hidden="true">7.7.</strong> 调试器</a></li></ol></li><li class="chapter-item expanded "><a href="statements-and-expressions.html"><strong aria-hidden="true">8.</strong> 语句和表达式</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="statements.html"><strong aria-hidden="true">8.1.</strong> 语句</a></li><li class="chapter-item expanded "><a href="expressions.html"><strong aria-hidden="true">8.2.</strong> 表达式</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="expressions/literal-expr.html"><strong aria-hidden="true">8.2.1.</strong> 字面量表达式</a></li><li class="chapter-item expanded "><a href="expressions/path-expr.html"><strong aria-hidden="true">8.2.2.</strong> 路径表达式</a></li><li class="chapter-item expanded "><a href="expressions/block-expr.html"><strong aria-hidden="true">8.2.3.</strong> 块表达式</a></li><li class="chapter-item expanded "><a href="expressions/operator-expr.html"><strong aria-hidden="true">8.2.4.</strong> 运算符表达式</a></li><li class="chapter-item expanded "><a href="expressions/grouped-expr.html"><strong aria-hidden="true">8.2.5.</strong> 分组表达式</a></li><li class="chapter-item expanded "><a href="expressions/array-expr.html"><strong aria-hidden="true">8.2.6.</strong> 数组和索引表达式</a></li><li class="chapter-item expanded "><a href="expressions/tuple-expr.html"><strong aria-hidden="true">8.2.7.</strong> 元组和索引表达式</a></li><li class="chapter-item expanded "><a href="expressions/struct-expr.html"><strong aria-hidden="true">8.2.8.</strong> 结构体表达式</a></li><li class="chapter-item expanded "><a href="expressions/call-expr.html"><strong aria-hidden="true">8.2.9.</strong> 调用表达式</a></li><li class="chapter-item expanded "><a href="expressions/method-call-expr.html"><strong aria-hidden="true">8.2.10.</strong> 方法调用表达式</a></li><li class="chapter-item expanded "><a href="expressions/field-expr.html"><strong aria-hidden="true">8.2.11.</strong> 字段访问表达式</a></li><li class="chapter-item expanded "><a href="expressions/closure-expr.html"><strong aria-hidden="true">8.2.12.</strong> 闭包表达式</a></li><li class="chapter-item expanded "><a href="expressions/loop-expr.html"><strong aria-hidden="true">8.2.13.</strong> 循环表达式</a></li><li class="chapter-item expanded "><a href="expressions/range-expr.html"><strong aria-hidden="true">8.2.14.</strong> 区间表达式</a></li><li class="chapter-item expanded "><a href="expressions/if-expr.html"><strong aria-hidden="true">8.2.15.</strong> if 和 if let 表达式</a></li><li class="chapter-item expanded "><a href="expressions/match-expr.html"><strong aria-hidden="true">8.2.16.</strong> 匹配表达式</a></li><li class="chapter-item expanded "><a href="expressions/return-expr.html"><strong aria-hidden="true">8.2.17.</strong> 返回表达式</a></li><li class="chapter-item expanded "><a href="expressions/await-expr.html"><strong aria-hidden="true">8.2.18.</strong> 等待(await)表达式</a></li><li class="chapter-item expanded "><a href="expressions/underscore-expr.html"><strong aria-hidden="true">8.2.19.</strong> 下划线表达式</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="patterns.html"><strong aria-hidden="true">9.</strong> 模式</a></li><li class="chapter-item expanded "><a href="type-system.html"><strong aria-hidden="true">10.</strong> 类型系统</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="types.html"><strong aria-hidden="true">10.1.</strong> 类型</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="types/boolean.html"><strong aria-hidden="true">10.1.1.</strong> 布尔型</a></li><li class="chapter-item expanded "><a href="types/numeric.html"><strong aria-hidden="true">10.1.2.</strong> 数字型</a></li><li class="chapter-item expanded "><a href="types/textual.html"><strong aria-hidden="true">10.1.3.</strong> 字符型</a></li><li class="chapter-item expanded "><a href="types/never.html"><strong aria-hidden="true">10.1.4.</strong> never类型</a></li><li class="chapter-item expanded "><a href="types/tuple.html"><strong aria-hidden="true">10.1.5.</strong> 元组</a></li><li class="chapter-item expanded "><a href="types/array.html"><strong aria-hidden="true">10.1.6.</strong> 数组</a></li><li class="chapter-item expanded "><a href="types/slice.html"><strong aria-hidden="true">10.1.7.</strong> 切片</a></li><li class="chapter-item expanded "><a href="types/struct.html"><strong aria-hidden="true">10.1.8.</strong> 结构体</a></li><li class="chapter-item expanded "><a href="types/enum.html"><strong aria-hidden="true">10.1.9.</strong> 枚举</a></li><li class="chapter-item expanded "><a href="types/union.html"><strong aria-hidden="true">10.1.10.</strong> 联合体</a></li><li class="chapter-item expanded "><a href="types/function-item.html"><strong aria-hidden="true">10.1.11.</strong> 函数项类型</a></li><li class="chapter-item expanded "><a href="types/closure.html"><strong aria-hidden="true">10.1.12.</strong> 闭包</a></li><li class="chapter-item expanded "><a href="types/pointer.html"><strong aria-hidden="true">10.1.13.</strong> 指针型</a></li><li class="chapter-item expanded "><a href="types/function-pointer.html"><strong aria-hidden="true">10.1.14.</strong> 函数指针</a></li><li class="chapter-item expanded "><a href="types/trait-object.html"><strong aria-hidden="true">10.1.15.</strong> trait对象</a></li><li class="chapter-item expanded "><a href="types/impl-trait.html"><strong aria-hidden="true">10.1.16.</strong> 实现trait</a></li><li class="chapter-item expanded "><a href="types/parameters.html"><strong aria-hidden="true">10.1.17.</strong> 类型参数</a></li><li class="chapter-item expanded "><a href="types/inferred.html"><strong aria-hidden="true">10.1.18.</strong> 可推断类型</a></li></ol></li><li class="chapter-item expanded "><a href="dynamically-sized-types.html"><strong aria-hidden="true">10.2.</strong> 动态内存宽度类型(DST)</a></li><li class="chapter-item expanded "><a href="type-layout.html"><strong aria-hidden="true">10.3.</strong> 类型布局 </a></li><li class="chapter-item expanded "><a href="interior-mutability.html"><strong aria-hidden="true">10.4.</strong> 内部可变性</a></li><li class="chapter-item expanded "><a href="subtyping.html"><strong aria-hidden="true">10.5.</strong> 子类型和型变</a></li><li class="chapter-item expanded "><a href="trait-bounds.html"><strong aria-hidden="true">10.6.</strong> trait约束及其生存期约束</a></li><li class="chapter-item expanded "><a href="type-coercions.html"><strong aria-hidden="true">10.7.</strong> 类型自动强转</a></li><li class="chapter-item expanded "><a href="destructors.html"><strong aria-hidden="true">10.8.</strong> 析构函数</a></li><li class="chapter-item expanded "><a href="lifetime-elision.html"><strong aria-hidden="true">10.9.</strong> 生存期省略</a></li></ol></li><li class="chapter-item expanded "><a href="special-types-and-traits.html"><strong aria-hidden="true">11.</strong> 特殊类型和 trait</a></li><li class="chapter-item expanded "><a href="names.html"><strong aria-hidden="true">12.</strong> 名称</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="names/namespaces.html"><strong aria-hidden="true">12.1.</strong> 命名空间</a></li><li class="chapter-item expanded "><a href="names/scopes.html"><strong aria-hidden="true">12.2.</strong> 作用域</a></li><li class="chapter-item expanded "><a href="names/preludes.html"><strong aria-hidden="true">12.3.</strong> 预导入包</a></li><li class="chapter-item expanded "><a href="paths.html"><strong aria-hidden="true">12.4.</strong> 路径</a></li><li class="chapter-item expanded "><a href="names/name-resolution.html"><strong aria-hidden="true">12.5.</strong> 名称解析</a></li><li class="chapter-item expanded "><a href="visibility-and-privacy.html"><strong aria-hidden="true">12.6.</strong> 可见性与隐私权</a></li></ol></li><li class="chapter-item expanded "><a href="memory-model.html"><strong aria-hidden="true">13.</strong> 内存模型</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="memory-allocation-and-lifetime.html"><strong aria-hidden="true">13.1.</strong> 内存分配和生存期</a></li><li class="chapter-item expanded "><a href="variables.html"><strong aria-hidden="true">13.2.</strong> 变量</a></li></ol></li><li class="chapter-item expanded "><a href="linkage.html"><strong aria-hidden="true">14.</strong> 链接</a></li><li class="chapter-item expanded "><a href="inline-assembly.html" class="active"><strong aria-hidden="true">15.</strong> 内联汇编</a></li><li class="chapter-item expanded "><a href="unsafety.html"><strong aria-hidden="true">16.</strong> 非安全性</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="unsafe-keyword.html"><strong aria-hidden="true">16.1.</strong> T关键字unsafe</a></li><li class="chapter-item expanded "><a href="behavior-considered-undefined.html"><strong aria-hidden="true">16.2.</strong> 未定义行为</a></li><li class="chapter-item expanded "><a href="behavior-not-considered-unsafe.html"><strong aria-hidden="true">16.3.</strong> 不被认为是非安全的行为</a></li></ol></li><li class="chapter-item expanded "><a href="const_eval.html"><strong aria-hidden="true">17.</strong> 常量求值</a></li><li class="chapter-item expanded "><a href="abi.html"><strong aria-hidden="true">18.</strong> ABI</a></li><li class="chapter-item expanded "><a href="runtime.html"><strong aria-hidden="true">19.</strong> Rust运行时</a></li><li class="chapter-item expanded "><a href="appendices.html"><strong aria-hidden="true">20.</strong> 附录</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="macro-ambiguity.html"><strong aria-hidden="true">20.1.</strong> 宏规范</a></li><li class="chapter-item expanded "><a href="influences.html"><strong aria-hidden="true">20.2.</strong> 影响来源</a></li><li class="chapter-item expanded "><a href="glossary.html"><strong aria-hidden="true">20.3.</strong> 术语表</a></li><li class="chapter-item expanded "><a href="本书术语翻译对照表.html"><strong aria-hidden="true">20.4.</strong> 本书术语翻译对照表</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle">
                <div class="sidebar-resize-indicator"></div>
            </div>
        </nav>

        <!-- Track and set sidebar scroll position -->
        <script>
            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
            sidebarScrollbox.addEventListener('click', function(e) {
                if (e.target.tagName === 'A') {
                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
                }
            }, { passive: true });
            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
            sessionStorage.removeItem('sidebar-scroll');
            if (sidebarScrollTop) {
                // preserve sidebar scroll position when navigating via links within sidebar
                sidebarScrollbox.scrollTop = sidebarScrollTop;
            } else {
                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
                var activeSection = document.querySelector('#sidebar .active');
                if (activeSection) {
                    activeSection.scrollIntoView({ block: 'center' });
                }
            }
        </script>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </label>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">The Rust Reference</h1>

                    <div class="right-buttons">
                        <a href="print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>
                        <a href="https://github.com/rust-lang/reference/" title="Git repository" aria-label="Git repository">
                            <i id="git-repository-button" class="fa fa-github"></i>
                        </a>
                        <a href="https://github.com/rust-lang/reference/edit/master/src/inline-assembly.md" title="Suggest an edit" aria-label="Suggest an edit">
                            <i id="git-edit-button" class="fa fa-edit"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="inline-assembly"><a class="header" href="#inline-assembly">Inline assembly</a></h1>
<h1 id="内联汇编"><a class="header" href="#内联汇编">内联汇编</a></h1>
<blockquote>
<p><a href="https://github.com/rust-lang/reference/blob/master/src/inline-assembly.md">behavior-considered-undefined.md</a><br />
commit: b8cc7336f61395de8034d05ccd50d4a2f21e6237 <br />
本章译文最后维护日期：2024-08-17</p>
</blockquote>
<div class="rule" id="asm"><a class="rule-link" href="#asm">[asm]</a></div>
<div class="rule" id="asm.intro"><a class="rule-link" href="#asm.intro">[asm.intro]</a></div>
<p>Rust 通过 <a href="https://doc.rust-lang.org/core/arch/macro.asm.html"><code>asm!</code></a> 和 <a href="https://doc.rust-lang.org/core/arch/macro.global_asm.html"><code>global_asm!</code></a> 这两个宏来提供了对内联汇编的支持。
它可用于在编译器生成的汇编程序输出中嵌入手写的汇编程序。</p>
<div class="rule" id="asm.stable-targets"><a class="rule-link" href="#asm.stable-targets">[asm.stable-targets]</a></div>
<p>目前对内联汇编的支持在以下目标架构上是稳定的：</p>
<ul>
<li>x86 和 x86-64</li>
<li>ARM</li>
<li>AArch64</li>
<li>RISC-V</li>
<li>LoongArch</li>
</ul>
<p>如果在不支持的目标架构上使用 <code>asm!</code>，编译器会报错。</p>
<h2 id="example"><a class="header" href="#example">Example</a></h2>
<h2 id="示例"><a class="header" href="#示例">示例</a></h2>
<div class="rule" id="asm.example"><a class="rule-link" href="#asm.example">[asm.example]</a></div>
<pre><pre class="playground"><code class="language-rust edition2021"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span><span class="boring">#[cfg(target_arch = "x86_64")] {
</span>use std::arch::asm;

// 使用以为和相加运算来实现 x 乘6的效果
let mut x: u64 = 4;
unsafe {
    asm!(
        "mov {tmp}, {x}",
        "shl {tmp}, 1",
        "shl {x}, 2",
        "add {x}, {tmp}",
        x = inout(reg) x,
        tmp = out(reg) _,
    );
}
assert_eq!(x, 4 * 6);
<span class="boring">}
</span><span class="boring">}</span></code></pre></pre>
<h2 id="syntax"><a class="header" href="#syntax">Syntax</a></h2>
<h2 id="句法"><a class="header" href="#句法">句法</a></h2>
<div class="rule" id="asm.syntax"><a class="rule-link" href="#asm.syntax">[asm.syntax]</a></div>
<p>下面的 ABNF语法规范指定了通用的内联汇编语法：</p>
<pre><code class="language-text">format_string := STRING_LITERAL / RAW_STRING_LITERAL
dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout"
reg_spec := &lt;register class&gt; / "\"" &lt;explicit register&gt; "\""
operand_expr := expr / "_" / expr "=&gt;" expr / expr "=&gt;" "_"
reg_operand := [ident "="] dir_spec "(" reg_spec ")" operand_expr / sym &lt;path&gt; / const &lt;expr&gt;
clobber_abi := "clobber_abi(" &lt;abi&gt; *("," &lt;abi&gt;) [","] ")"
option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw"
options := "options(" option *("," option) [","] ")"
operand := reg_operand / clobber_abi / options
asm := "asm!(" format_string *("," format_string) *("," operand) [","] ")"
global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")"
</code></pre>
<h2 id="scope"><a class="header" href="#scope">Scope</a></h2>
<h2 id="作用域"><a class="header" href="#作用域">作用域</a></h2>
<div class="rule" id="asm.scope"><a class="rule-link" href="#asm.scope">[asm.scope]</a></div>
<div class="rule" id="asm.scope.intro"><a class="rule-link" href="#asm.scope.intro">[asm.scope.intro]</a></div>
<p>内联汇编可以以下面两种方式来使用。</p>
<div class="rule" id="asm.scope.asm"><a class="rule-link" href="#asm.scope.asm">[asm.scope.asm]</a></div>
<p>通过 <code>asm!</code>宏，汇编代码在函数作用域中被发射，且最终被集成到编译器生成的函数的汇编代码中。
此汇编代码必须遵守 <a href="#rules-for-inline-assembly">严格规则</a>以避免未定义行为。
注意，在某些情况下，编译器可能选择将汇编代码作为一个独立的函数发射，并生成对它的调用汇编。</p>
<div class="rule" id="asm.scope.global_asm"><a class="rule-link" href="#asm.scope.global_asm">[asm.scope.global_asm]</a></div>
<p>通过 <code>global_asm!</code>宏，汇编代码在全局作用域中被发射。
这可以用来使用汇编代码编写完整的函数，并且通常提供更多的自由来使用任意寄存器和汇编指令。</p>
<h2 id="template-string-arguments"><a class="header" href="#template-string-arguments">Template string arguments</a></h2>
<h2 id="模板字符串参数"><a class="header" href="#模板字符串参数">模板字符串参数</a></h2>
<div class="rule" id="asm.ts-args"><a class="rule-link" href="#asm.ts-args">[asm.ts-args]</a></div>
<div class="rule" id="asm.ts-args.syntax"><a class="rule-link" href="#asm.ts-args.syntax">[asm.ts-args.syntax]</a></div>
<p>汇编器模板使用与<a href="../std/fmt/index.html#syntax">格式字符串</a>相同的语法(即占位符是由一对花括号来标定)。</p>
<div class="rule" id="asm.ts-args.order"><a class="rule-link" href="#asm.ts-args.order">[asm.ts-args.order]</a></div>
<p>相应的参数通过顺序、索引或名称来获取。</p>
<div class="rule" id="asm.ts-args.no-implicit"><a class="rule-link" href="#asm.ts-args.no-implicit">[asm.ts-args.no-implicit]</a></div>
<p>但是不支持隐式的命名参数（<a href="https://github.com/rust-lang/rfcs/pull/2795">RFC #2795</a>引入）。</p>
<div class="rule" id="asm.ts-args.one-or-more"><a class="rule-link" href="#asm.ts-args.one-or-more">[asm.ts-args.one-or-more]</a></div>
<p><code>asm!</code>宏调用可以有一个或多个模板字符串参数；带有多个模板字符串参数的 <code>asm!</code> 的所有字符串参数都会被视为用 <code>\n</code> 连接在了一起的大的字符串。
预期的用法是每个模板字符串参数对应一行汇编代码。</p>
<div class="rule" id="asm.ts-args.before-other-args"><a class="rule-link" href="#asm.ts-args.before-other-args">[asm.ts-args.before-other-args]</a></div>
<p>所有的模板字符串参数必须放在其他类型的参数之前。</p>
<div class="rule" id="asm.ts-args.positional-first"><a class="rule-link" href="#asm.ts-args.positional-first">[asm.ts-args.positional-first]</a></div>
<p>和格式字符串一样，命名参数必须在位置参数之后出现。
与格式字符串一样，位置参数必须出现在命名参数和显式<a href="#register-operands">寄存器操作</a>之前。</p>
<div class="rule" id="asm.ts-args.register-operands"><a class="rule-link" href="#asm.ts-args.register-operands">[asm.ts-args.register-operands]</a></div>
<p>在模板字符串中，占位符不能使用（带有）显式寄存器的操作。</p>
<div class="rule" id="asm.ts-args.at-least-once"><a class="rule-link" href="#asm.ts-args.at-least-once">[asm.ts-args.at-least-once]</a></div>
<p>所有其他命名操作和位置操作必须在模板字符串中至少出现一次，否则将生成编译器错误。</p>
<div class="rule" id="asm.ts-args.opaque"><a class="rule-link" href="#asm.ts-args.opaque">[asm.ts-args.opaque]</a></div>
<p>确切的汇编代码语法是特定于目标架构的，对于编译器来说是不透明的，当然除了编译器可以将各种操作类型去替换模板字符串以形成能传递给汇编器的汇编代码。</p>
<div class="rule" id="asm.ts-args.llvm-syntax"><a class="rule-link" href="#asm.ts-args.llvm-syntax">[asm.ts-args.llvm-syntax]</a></div>
<p>目前，所有支持的目标架构都遵循 LLVM 内部汇编器使用的汇编代码语法，这通常对应于 GNU汇编器(GAS)。
x86目标架构上，默认使用 GAS的 <code>.intel_syntax noprefix</code>模式。
ARM目标架构上，使用 <code>.syntax unified</code>模式。
这些目标架构对汇编代码做了一些额外的限制：任何汇编器状态（例如，可以使用 <code>.section</code> 更改的当前节）必须在 asm字符串末尾恢复为其原始值。
不符合 GAS语法的汇编代码将导致特定于汇编器的行为。
对内联汇编使用的指令的进一步的约束在本章后面的<a href="#directives-support">指令支持</a>章节有详细说明。</p>
<h2 id="operand-type"><a class="header" href="#operand-type">Operand type</a></h2>
<h2 id="操作类型"><a class="header" href="#操作类型">操作类型</a></h2>
<div class="rule" id="asm.operand-type"><a class="rule-link" href="#asm.operand-type">[asm.operand-type]</a></div>
<div class="rule" id="asm.operand-type.supported-operands"><a class="rule-link" href="#asm.operand-type.supported-operands">[asm.operand-type.supported-operands]</a></div>
<p>目前支持以下几种类型的操作：</p>
<div class="rule" id="asm.operand-type.supported-operands.in"><a class="rule-link" href="#asm.operand-type.supported-operands.in">[asm.operand-type.supported-operands.in]</a></div>
<ul>
<li><code>in(&lt;reg&gt;) &lt;expr&gt;</code>
<ul>
<li><code>&lt;reg&gt;</code> 可以指向某类寄存器或一个显式的寄存器。
此已分配的寄存器名会被替换到 asm模板字符串中。</li>
<li>在这段 asm代码的开头，此已分配的寄存器将包含 <code>&lt;expr&gt;</code> 的值。</li>
<li>在这段 asm代码的结尾，该寄存器内的值必须恢复如初（除了另有 <code>lateout</code>操作也被分配使用了此寄存器）。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.operand-type.supported-operands.out"><a class="rule-link" href="#asm.operand-type.supported-operands.out">[asm.operand-type.supported-operands.out]</a></div>
<ul>
<li><code>out(&lt;reg&gt;) &lt;expr&gt;</code>
<ul>
<li><code>&lt;reg&gt;</code> 可以指向某类寄存器或一个显式的寄存器。
此已分配的寄存器名会被替换到 asm模板字符串中。</li>
<li>在这段 asm代码的开头，此已分配的寄存器将包含一个未定义的值。</li>
<li><code>&lt;expr&gt;</code> 必须是一个（可能未被初始化的）位置表达式，在这段 asm代码的结尾，此寄存器的内容会被写到此位置表达式里。</li>
<li>可以使用下划线(<code>_</code>)替代这个位置表达式，这将导致在这段 asm代码的结尾，此寄存器的内容被丢弃(等效于一个 clobber寄存器（译者注：clobber寄存器会被该asm语句中的汇编代码隐性修改，也因此，编译器在为输入操作数和输出操作数挑选寄存器时，就不会使用这类寄存器，这样就避免了发生数据覆盖等逻辑错误)。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.operand-type.supported-operands.lateout"><a class="rule-link" href="#asm.operand-type.supported-operands.lateout">[asm.operand-type.supported-operands.lateout]</a></div>
<ul>
<li><code>lateout(&lt;reg&gt;) &lt;expr&gt;</code>
<ul>
<li>除了寄存器分配器可以重用分配给 <code>in</code> 的寄存器外，其他的同 <code>out</code>。</li>
<li>应该只在读取所有输入后才写入此寄存器，否则可能会毁坏真实的输入。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.operand-type.supported-operands.inout"><a class="rule-link" href="#asm.operand-type.supported-operands.inout">[asm.operand-type.supported-operands.inout]</a></div>
<ul>
<li><code>inout(&lt;reg&gt;) &lt;expr&gt;</code>
<ul>
<li><code>&lt;reg&gt;</code> 可以指向某类寄存器或一个显式的寄存器。
此已分配的寄存器名会被替换到 asm模板字符串中。</li>
<li>在这段 asm代码的开头，此已分配的寄存器将包含 <code>&lt;expr&gt;</code> 的值。</li>
<li><code>&lt;expr&gt;</code> 必须是一个可变的已初始化的位置表达式，在这段 asm代码的结尾，此已分配的寄存器内的内容将会被写入此表达式。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.operand-type.supported-operands.inout-arrow"><a class="rule-link" href="#asm.operand-type.supported-operands.inout-arrow">[asm.operand-type.supported-operands.inout-arrow]</a></div>
<ul>
<li><code>inout(&lt;reg&gt;) &lt;in expr&gt; =&gt; &lt;out expr&gt;</code>
<ul>
<li>除了从 <code>&lt;in expr&gt;</code> 里取值来初始化此寄存器外，其他的同 <code>inout</code>。</li>
<li><code>&lt;out expr&gt;</code> 必须是一个（可能未被初始化的）位置表达式，在这段 asm代码的结尾，此寄存器的内容会被写到此位置表达式里。</li>
<li>可以使用下划线(<code>_</code>)替代这个 <code>&lt;out expr&gt;</code>表达式，这将导致在这段 asm代码的结尾，此寄存器的内容被丢弃(等效于一个 clobber寄存器)。</li>
<li><code>&lt;in expr&gt;</code> 和 <code>&lt;out expr&gt;</code> 可以有不同的类型。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.operand-type.supported-operands.inlateout"><a class="rule-link" href="#asm.operand-type.supported-operands.inlateout">[asm.operand-type.supported-operands.inlateout]</a></div>
<ul>
<li><code>inlateout(&lt;reg&gt;) &lt;expr&gt;</code> / <code>inlateout(&lt;reg&gt;) &lt;in expr&gt; =&gt; &lt;out expr&gt;</code>
<ul>
<li>除了寄存器分配器可以重用分配给 <code>in</code> 的寄存器外（如果编译器知道 <code>in</code> 与 <code>inlateout</code> 具有相同的初始值，则可能发生这种情况），其他的同 <code>inout</code>。</li>
<li>应该只在读取所有输入后才写入此寄存器，否则可能会毁坏真实的输入。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.operand-type.supported-operands.sym"><a class="rule-link" href="#asm.operand-type.supported-operands.sym">[asm.operand-type.supported-operands.sym]</a></div>
<ul>
<li>
<p><code>sym &lt;path&gt;</code></p>
<ul>
<li><code>&lt;path&gt;</code> 必须指向一个 <code>fn</code>程序项 或 <code>static</code>程序项。</li>
<li>引用该程序项的混淆符号名（mangled symbol）称被替换为 asm模板字符串。</li>
<li>替换的字符串不包含任何修饰符（例如GOT、PLT、重定位等）。</li>
<li><code>&lt;path&gt;</code>允许指向<code>#[thread_local]</code>静态项，在这种情况下，asm代码可以将符号与重定位（例如<code>@plt</code>、<code>@TPOFF</code>）结合起来，来从线程内的本地变量中读取数据。</li>
</ul>
</li>
<li>
<p><code>const &lt;expr&gt;</code></p>
<ul>
<li><code>&lt;expr&gt;</code>必须是整型常量表达式。此表达式遵循与内联 <code>const</code>块相同的规则。</li>
<li>表达式的类型可以是任何整数类型，但默认为 <code>i32</code>，就像整型字面量一样。</li>
<li>表达式的值被格式化为字符串，并直接替换为 asm模板字符串。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.operand-type.left-to-right"><a class="rule-link" href="#asm.operand-type.left-to-right">[asm.operand-type.left-to-right]</a></div>
<p>操作表达式从左到右求值，就像函数调用参数一样。
在 <code>asm!</code>执行后，会按从左到右的顺序写出输出。
这一点很重要，如果两个输出指向同一个位置：该位置（表达式）将包含最右侧输出的值。</p>
<div class="rule" id="asm.operand-type.global_asm-restriction"><a class="rule-link" href="#asm.operand-type.global_asm-restriction">[asm.operand-type.global_asm-restriction]</a></div>
<p>因为 <code>global_asm!</code> 存在于函数外部，它只能使用 <code>sym</code>操作 和 <code>const</code>操作。</p>
<h2 id="register-operands"><a class="header" href="#register-operands">Register operands</a></h2>
<h2 id="寄存器操作"><a class="header" href="#寄存器操作">寄存器操作</a></h2>
<div class="rule" id="asm.register-operands"><a class="rule-link" href="#asm.register-operands">[asm.register-operands]</a></div>
<div class="rule" id="asm.register-operands.register-or-class"><a class="rule-link" href="#asm.register-operands.register-or-class">[asm.register-operands.register-or-class]</a></div>
<p>输入和输出操作可以被用来指定一个显式寄存器或某一类寄存器（可以被寄存器分配器选择和分配的一类寄存器，每次可以从中选择和分配其中的一个）。
显式寄存器是被字符串文本（例如 <code>"eax"</code>）指定的，而寄存器类是通过标识符（例如 <code>reg</code>）来指定的。</p>
<div class="rule" id="asm.register-operands.equivalence-to-base-register"><a class="rule-link" href="#asm.register-operands.equivalence-to-base-register">[asm.register-operands.equivalence-to-base-register]</a></div>
<p>请注意，显式寄存器将寄存器别名（例如ARM上的 <code>r14</code> 和 <code>lr</code>）和寄存器的较小视图（例如 <code>eax</code> 和 <code>rax</code>）视为与其基寄存器(base register)等效。</p>
<div class="rule" id="asm.register-operands.error-two-operands"><a class="rule-link" href="#asm.register-operands.error-two-operands">[asm.register-operands.error-two-operands]</a></div>
<p>对两个输入操作或两个输出操作使用相同的显式寄存器会在编译期报错。</p>
<div class="rule" id="asm.register-operands.error-overlapping"><a class="rule-link" href="#asm.register-operands.error-overlapping">[asm.register-operands.error-overlapping]</a></div>
<p>此外，在输入操作或输出操作中发生寄存器重叠（如ARM VFP）也会在编译期报错。</p>
<div class="rule" id="asm.register-operands.allowed-types"><a class="rule-link" href="#asm.register-operands.allowed-types">[asm.register-operands.allowed-types]</a></div>
<p>仅允许以下类型的值作为的内联汇编操作：</p>
<ul>
<li>整型 (有符号的和无符号的)</li>
<li>浮点型数值</li>
<li>指针 (仅廋指针)</li>
<li>函数指针</li>
<li>SIMD向量 (使用 <code>#[repr(simd)]</code> 定义的并且实现了 <code>Copy</code> 的结构体)。
这包括在 <code>std::arch</code> 中定义的特定于体系架构的向量类型，如 <code>__m128</code> (x86) 或 <code>int8x16_t</code> (ARM)。</li>
</ul>
<div class="rule" id="asm.register-operands.supported-register-classes"><a class="rule-link" href="#asm.register-operands.supported-register-classes">[asm.register-operands.supported-register-classes]</a></div>
<p>以下是当前支持的寄存器类列表：</p>
<div class="table-wrapper"><table><thead><tr><th>体系架构</th><th>寄存器类</th><th>寄存器</th><th>LLVM约束代码</th></tr></thead><tbody>
<tr><td>x86</td><td><code>reg</code></td><td><code>ax</code>, <code>bx</code>, <code>cx</code>, <code>dx</code>, <code>si</code>, <code>di</code>, <code>bp</code>, <code>r[8-15]</code> (仅 x86-64)</td><td><code>r</code></td></tr>
<tr><td>x86</td><td><code>reg_abcd</code></td><td><code>ax</code>, <code>bx</code>, <code>cx</code>, <code>dx</code></td><td><code>Q</code></td></tr>
<tr><td>x86-32</td><td><code>reg_byte</code></td><td><code>al</code>, <code>bl</code>, <code>cl</code>, <code>dl</code>, <code>ah</code>, <code>bh</code>, <code>ch</code>, <code>dh</code></td><td><code>q</code></td></tr>
<tr><td>x86-64</td><td><code>reg_byte</code>*</td><td><code>al</code>, <code>bl</code>, <code>cl</code>, <code>dl</code>, <code>sil</code>, <code>dil</code>, <code>bpl</code>, <code>r[8-15]b</code></td><td><code>q</code></td></tr>
<tr><td>x86</td><td><code>xmm_reg</code></td><td><code>xmm[0-7]</code> (x86) <code>xmm[0-15]</code> (x86-64)</td><td><code>x</code></td></tr>
<tr><td>x86</td><td><code>ymm_reg</code></td><td><code>ymm[0-7]</code> (x86) <code>ymm[0-15]</code> (x86-64)</td><td><code>x</code></td></tr>
<tr><td>x86</td><td><code>zmm_reg</code></td><td><code>zmm[0-7]</code> (x86) <code>zmm[0-31]</code> (x86-64)</td><td><code>v</code></td></tr>
<tr><td>x86</td><td><code>kreg</code></td><td><code>k[1-7]</code></td><td><code>Yk</code></td></tr>
<tr><td>x86</td><td><code>kreg0</code></td><td><code>k0</code></td><td>仅 clobbers</td></tr>
<tr><td>x86</td><td><code>x87_reg</code></td><td><code>st([0-7])</code></td><td>仅 clobbers</td></tr>
<tr><td>x86</td><td><code>mmx_reg</code></td><td><code>mm[0-7]</code></td><td>仅 clobbers</td></tr>
<tr><td>x86-64</td><td><code>tmm_reg</code></td><td><code>tmm[0-7]</code></td><td>仅 clobbers</td></tr>
<tr><td>AArch64</td><td><code>reg</code></td><td><code>x[0-30]</code></td><td><code>r</code></td></tr>
<tr><td>AArch64</td><td><code>vreg</code></td><td><code>v[0-31]</code></td><td><code>w</code></td></tr>
<tr><td>AArch64</td><td><code>vreg_low16</code></td><td><code>v[0-15]</code></td><td><code>x</code></td></tr>
<tr><td>AArch64</td><td><code>preg</code></td><td><code>p[0-15]</code>, <code>ffr</code></td><td>仅 clobbers</td></tr>
<tr><td>ARM (ARM/Thumb2)</td><td><code>reg</code></td><td><code>r[0-12]</code>, <code>r14</code></td><td><code>r</code></td></tr>
<tr><td>ARM (Thumb1)</td><td><code>reg</code></td><td><code>r[0-7]</code></td><td><code>r</code></td></tr>
<tr><td>ARM</td><td><code>sreg</code></td><td><code>s[0-31]</code></td><td><code>t</code></td></tr>
<tr><td>ARM</td><td><code>sreg_low16</code></td><td><code>s[0-15]</code></td><td><code>x</code></td></tr>
<tr><td>ARM</td><td><code>dreg</code></td><td><code>d[0-31]</code></td><td><code>w</code></td></tr>
<tr><td>ARM</td><td><code>dreg_low16</code></td><td><code>d[0-15]</code></td><td><code>t</code></td></tr>
<tr><td>ARM</td><td><code>dreg_low8</code></td><td><code>d[0-8]</code></td><td><code>x</code></td></tr>
<tr><td>ARM</td><td><code>qreg</code></td><td><code>q[0-15]</code></td><td><code>w</code></td></tr>
<tr><td>ARM</td><td><code>qreg_low8</code></td><td><code>q[0-7]</code></td><td><code>t</code></td></tr>
<tr><td>ARM</td><td><code>qreg_low4</code></td><td><code>q[0-3]</code></td><td><code>x</code></td></tr>
<tr><td>RISC-V</td><td><code>reg</code></td><td><code>x1</code>, <code>x[5-7]</code>, <code>x[9-15]</code>, <code>x[16-31]</code> (non-RV32E)</td><td><code>r</code></td></tr>
<tr><td>RISC-V</td><td><code>freg</code></td><td><code>f[0-31]</code></td><td><code>f</code></td></tr>
<tr><td>RISC-V</td><td><code>vreg</code></td><td><code>v[0-31]</code></td><td>仅 clobbers</td></tr>
<tr><td>LoongArch</td><td><code>reg</code></td><td><code>$r1</code>, <code>$r[4-20]</code>, <code>$r[23,30]</code></td><td><code>r</code></td></tr>
<tr><td>LoongArch</td><td><code>freg</code></td><td><code>$f[0-31]</code></td><td><code>f</code></td></tr>
</tbody></table>
</div>
<blockquote>
<p><strong>注意</strong>:</p>
<ul>
<li>在x86上，我们将 <code>reg_byte</code> 与 reg<code>区别对待，因为编译器可以为</code>reg_byte<code>分别分配低位的 'al' 和高位的 'ah'，而</code>reg` 却只能持有整个寄存器。</li>
<li>在x86-64上，<code>reg_byte</code>寄存器类中没有高位寄存器（例如没有 <code>ah</code>）。</li>
<li>一些寄存器类被标记为 “仅 clobbers” 意味着此类中的寄存器不能被用于输入或输出，只能用于 <code>out(&lt;explicit register&gt;) _</code> 或 <code>lateout(&lt;explicit register&gt;) _</code> 这样的表达形式的。</li>
</ul>
</blockquote>
<div class="rule" id="asm.register-operands.value-type-constraints"><a class="rule-link" href="#asm.register-operands.value-type-constraints">[asm.register-operands.value-type-constraints]</a></div>
<p>每个寄存器类都有可以与之一起使用的值类型的约束。
这是必要的，因为值被加载到寄存器的方式取决于它的类型。
例如，在大端机系统上，将 <code>i32x4</code> 和 <code>i8x16</code> 加载到 SIMD寄存器可能会导致不同的寄存器内容，即便这两个值的字节内存表示形式相同。
特定寄存器类支持的类型的可用性可能取决于当前启用的目标特性。</p>
<div class="table-wrapper"><table><thead><tr><th>体系架构</th><th>寄存器类</th><th>目标特性</th><th>允许的类型</th></tr></thead><tbody>
<tr><td>x86-32</td><td><code>reg</code></td><td>None</td><td><code>i16</code>, <code>i32</code>, <code>f32</code></td></tr>
<tr><td>x86-64</td><td><code>reg</code></td><td>None</td><td><code>i16</code>, <code>i32</code>, <code>f32</code>, <code>i64</code>, <code>f64</code></td></tr>
<tr><td>x86</td><td><code>reg_byte</code></td><td>None</td><td><code>i8</code></td></tr>
<tr><td>x86</td><td><code>xmm_reg</code></td><td><code>sse</code></td><td><code>i32</code>, <code>f32</code>, <code>i64</code>, <code>f64</code>, <br> <code>i8x16</code>, <code>i16x8</code>, <code>i32x4</code>, <code>i64x2</code>, <code>f32x4</code>, <code>f64x2</code></td></tr>
<tr><td>x86</td><td><code>ymm_reg</code></td><td><code>avx</code></td><td><code>i32</code>, <code>f32</code>, <code>i64</code>, <code>f64</code>, <br> <code>i8x16</code>, <code>i16x8</code>, <code>i32x4</code>, <code>i64x2</code>, <code>f32x4</code>, <code>f64x2</code> <br> <code>i8x32</code>, <code>i16x16</code>, <code>i32x8</code>, <code>i64x4</code>, <code>f32x8</code>, <code>f64x4</code></td></tr>
<tr><td>x86</td><td><code>zmm_reg</code></td><td><code>avx512f</code></td><td><code>i32</code>, <code>f32</code>, <code>i64</code>, <code>f64</code>, <br> <code>i8x16</code>, <code>i16x8</code>, <code>i32x4</code>, <code>i64x2</code>, <code>f32x4</code>, <code>f64x2</code> <br> <code>i8x32</code>, <code>i16x16</code>, <code>i32x8</code>, <code>i64x4</code>, <code>f32x8</code>, <code>f64x4</code> <br> <code>i8x64</code>, <code>i16x32</code>, <code>i32x16</code>, <code>i64x8</code>, <code>f32x16</code>, <code>f64x8</code></td></tr>
<tr><td>x86</td><td><code>kreg</code></td><td><code>avx512f</code></td><td><code>i8</code>, <code>i16</code></td></tr>
<tr><td>x86</td><td><code>kreg</code></td><td><code>avx512bw</code></td><td><code>i32</code>, <code>i64</code></td></tr>
<tr><td>x86</td><td><code>mmx_reg</code></td><td>N/A</td><td>仅 clobbers</td></tr>
<tr><td>x86</td><td><code>x87_reg</code></td><td>N/A</td><td>仅 clobbers</td></tr>
<tr><td>x86</td><td><code>tmm_reg</code></td><td>N/A</td><td>仅 clobbers</td></tr>
<tr><td>AArch64</td><td><code>reg</code></td><td>None</td><td><code>i8</code>, <code>i16</code>, <code>i32</code>, <code>f32</code>, <code>i64</code>, <code>f64</code></td></tr>
<tr><td>AArch64</td><td><code>vreg</code></td><td><code>neon</code></td><td><code>i8</code>, <code>i16</code>, <code>i32</code>, <code>f32</code>, <code>i64</code>, <code>f64</code>, <br> <code>i8x8</code>, <code>i16x4</code>, <code>i32x2</code>, <code>i64x1</code>, <code>f32x2</code>, <code>f64x1</code>, <br> <code>i8x16</code>, <code>i16x8</code>, <code>i32x4</code>, <code>i64x2</code>, <code>f32x4</code>, <code>f64x2</code></td></tr>
<tr><td>AArch64</td><td><code>preg</code></td><td>N/A</td><td>仅 clobbers</td></tr>
<tr><td>ARM</td><td><code>reg</code></td><td>None</td><td><code>i8</code>, <code>i16</code>, <code>i32</code>, <code>f32</code></td></tr>
<tr><td>ARM</td><td><code>sreg</code></td><td><code>vfp2</code></td><td><code>i32</code>, <code>f32</code></td></tr>
<tr><td>ARM</td><td><code>dreg</code></td><td><code>vfp2</code></td><td><code>i64</code>, <code>f64</code>, <code>i8x8</code>, <code>i16x4</code>, <code>i32x2</code>, <code>i64x1</code>, <code>f32x2</code></td></tr>
<tr><td>ARM</td><td><code>qreg</code></td><td><code>neon</code></td><td><code>i8x16</code>, <code>i16x8</code>, <code>i32x4</code>, <code>i64x2</code>, <code>f32x4</code></td></tr>
<tr><td>RISC-V32</td><td><code>reg</code></td><td>None</td><td><code>i8</code>, <code>i16</code>, <code>i32</code>, <code>f32</code></td></tr>
<tr><td>RISC-V64</td><td><code>reg</code></td><td>None</td><td><code>i8</code>, <code>i16</code>, <code>i32</code>, <code>f32</code>, <code>i64</code>, <code>f64</code></td></tr>
<tr><td>RISC-V</td><td><code>freg</code></td><td><code>f</code></td><td><code>f32</code></td></tr>
<tr><td>RISC-V</td><td><code>freg</code></td><td><code>d</code></td><td><code>f64</code></td></tr>
<tr><td>RISC-V</td><td><code>vreg</code></td><td>N/A</td><td>仅 clobbers</td></tr>
<tr><td>LoongArch64</td><td><code>reg</code></td><td>None</td><td><code>i8</code>, <code>i16</code>, <code>i32</code>, <code>i64</code>, <code>f32</code>, <code>f64</code></td></tr>
<tr><td>LoongArch64</td><td><code>freg</code></td><td>None</td><td><code>f32</code>, <code>f64</code></td></tr>
</tbody></table>
</div>
<blockquote>
<p><strong>注意</strong>: 对于上述表里，指针、函数指针和 <code>isize</code>/<code>usize</code> 被视为等效的整数类型（<code>i16</code>/<code>i32</code>/<code>i64</code> 具体取决于目标架构）。</p>
</blockquote>
<div class="rule" id="asm.register-operands.smaller-value"><a class="rule-link" href="#asm.register-operands.smaller-value">[asm.register-operands.smaller-value]</a></div>
<p>如果某个值的内存宽度小于分配给它的寄存器，则在输入时该寄存器的高位将有一个未定义的输入值，输出时将忽略该寄存器的高位值。
唯一的例外是 RISC-V 上的 <code>freg</code>寄存器类，其中 <code>f32</code> 值按照 RISC-V 体系架构的要求被以 NaN-boxed的形式表达为 <code>f64</code>。</p>
<div class="rule" id="asm.register-operands.separate-input-output"><a class="rule-link" href="#asm.register-operands.separate-input-output">[asm.register-operands.separate-input-output]</a></div>
<p>当为 <code>inout</code>操作分别指定了输入和输出表达式时，这两个表达式必须具有相同的数据类型。
唯一的例外是两个操作（所操作的表达式）都是指针或整数时，它们只需要具有相同的类型内存宽度。
存在此约束是因为 LLVM 和 GCC 中的寄存器分配器有时无法让既定的操作(operand)和不同的数据类型进行有效绑定。</p>
<h2 id="register-names"><a class="header" href="#register-names">Register names</a></h2>
<h2 id="寄存器名称"><a class="header" href="#寄存器名称">寄存器名称</a></h2>
<div class="rule" id="asm.register-names"><a class="rule-link" href="#asm.register-names">[asm.register-names]</a></div>
<div class="rule" id="asm.register-names.supported-register-aliases"><a class="rule-link" href="#asm.register-names.supported-register-aliases">[asm.register-names.supported-register-aliases]</a></div>
<p>一些寄存器有多个名称。
编译器会将它们视为与其基寄存器名称相同。
以下是所有受支持的寄存器别名的列表：</p>
<div class="table-wrapper"><table><thead><tr><th>体系架构</th><th>基寄存器</th><th>别名</th></tr></thead><tbody>
<tr><td>x86</td><td><code>ax</code></td><td><code>eax</code>, <code>rax</code></td></tr>
<tr><td>x86</td><td><code>bx</code></td><td><code>ebx</code>, <code>rbx</code></td></tr>
<tr><td>x86</td><td><code>cx</code></td><td><code>ecx</code>, <code>rcx</code></td></tr>
<tr><td>x86</td><td><code>dx</code></td><td><code>edx</code>, <code>rdx</code></td></tr>
<tr><td>x86</td><td><code>si</code></td><td><code>esi</code>, <code>rsi</code></td></tr>
<tr><td>x86</td><td><code>di</code></td><td><code>edi</code>, <code>rdi</code></td></tr>
<tr><td>x86</td><td><code>bp</code></td><td><code>bpl</code>, <code>ebp</code>, <code>rbp</code></td></tr>
<tr><td>x86</td><td><code>sp</code></td><td><code>spl</code>, <code>esp</code>, <code>rsp</code></td></tr>
<tr><td>x86</td><td><code>ip</code></td><td><code>eip</code>, <code>rip</code></td></tr>
<tr><td>x86</td><td><code>st(0)</code></td><td><code>st</code></td></tr>
<tr><td>x86</td><td><code>r[8-15]</code></td><td><code>r[8-15]b</code>, <code>r[8-15]w</code>, <code>r[8-15]d</code></td></tr>
<tr><td>x86</td><td><code>xmm[0-31]</code></td><td><code>ymm[0-31]</code>, <code>zmm[0-31]</code></td></tr>
<tr><td>AArch64</td><td><code>x[0-30]</code></td><td><code>w[0-30]</code></td></tr>
<tr><td>AArch64</td><td><code>x29</code></td><td><code>fp</code></td></tr>
<tr><td>AArch64</td><td><code>x30</code></td><td><code>lr</code></td></tr>
<tr><td>AArch64</td><td><code>sp</code></td><td><code>wsp</code></td></tr>
<tr><td>AArch64</td><td><code>xzr</code></td><td><code>wzr</code></td></tr>
<tr><td>AArch64</td><td><code>v[0-31]</code></td><td><code>b[0-31]</code>, <code>h[0-31]</code>, <code>s[0-31]</code>, <code>d[0-31]</code>, <code>q[0-31]</code></td></tr>
<tr><td>ARM</td><td><code>r[0-3]</code></td><td><code>a[1-4]</code></td></tr>
<tr><td>ARM</td><td><code>r[4-9]</code></td><td><code>v[1-6]</code></td></tr>
<tr><td>ARM</td><td><code>r9</code></td><td><code>rfp</code></td></tr>
<tr><td>ARM</td><td><code>r10</code></td><td><code>sl</code></td></tr>
<tr><td>ARM</td><td><code>r11</code></td><td><code>fp</code></td></tr>
<tr><td>ARM</td><td><code>r12</code></td><td><code>ip</code></td></tr>
<tr><td>ARM</td><td><code>r13</code></td><td><code>sp</code></td></tr>
<tr><td>ARM</td><td><code>r14</code></td><td><code>lr</code></td></tr>
<tr><td>ARM</td><td><code>r15</code></td><td><code>pc</code></td></tr>
<tr><td>RISC-V</td><td><code>x0</code></td><td><code>zero</code></td></tr>
<tr><td>RISC-V</td><td><code>x1</code></td><td><code>ra</code></td></tr>
<tr><td>RISC-V</td><td><code>x2</code></td><td><code>sp</code></td></tr>
<tr><td>RISC-V</td><td><code>x3</code></td><td><code>gp</code></td></tr>
<tr><td>RISC-V</td><td><code>x4</code></td><td><code>tp</code></td></tr>
<tr><td>RISC-V</td><td><code>x[5-7]</code></td><td><code>t[0-2]</code></td></tr>
<tr><td>RISC-V</td><td><code>x8</code></td><td><code>fp</code>, <code>s0</code></td></tr>
<tr><td>RISC-V</td><td><code>x9</code></td><td><code>s1</code></td></tr>
<tr><td>RISC-V</td><td><code>x[10-17]</code></td><td><code>a[0-7]</code></td></tr>
<tr><td>RISC-V</td><td><code>x[18-27]</code></td><td><code>s[2-11]</code></td></tr>
<tr><td>RISC-V</td><td><code>x[28-31]</code></td><td><code>t[3-6]</code></td></tr>
<tr><td>RISC-V</td><td><code>f[0-7]</code></td><td><code>ft[0-7]</code></td></tr>
<tr><td>RISC-V</td><td><code>f[8-9]</code></td><td><code>fs[0-1]</code></td></tr>
<tr><td>RISC-V</td><td><code>f[10-17]</code></td><td><code>fa[0-7]</code></td></tr>
<tr><td>RISC-V</td><td><code>f[18-27]</code></td><td><code>fs[2-11]</code></td></tr>
<tr><td>RISC-V</td><td><code>f[28-31]</code></td><td><code>ft[8-11]</code></td></tr>
<tr><td>LoongArch</td><td><code>$r0</code></td><td><code>$zero</code></td></tr>
<tr><td>LoongArch</td><td><code>$r1</code></td><td><code>$ra</code></td></tr>
<tr><td>LoongArch</td><td><code>$r2</code></td><td><code>$tp</code></td></tr>
<tr><td>LoongArch</td><td><code>$r3</code></td><td><code>$sp</code></td></tr>
<tr><td>LoongArch</td><td><code>$r[4-11]</code></td><td><code>$a[0-7]</code></td></tr>
<tr><td>LoongArch</td><td><code>$r[12-20]</code></td><td><code>$t[0-8]</code></td></tr>
<tr><td>LoongArch</td><td><code>$r21</code></td><td></td></tr>
<tr><td>LoongArch</td><td><code>$r22</code></td><td><code>$fp</code>, <code>$s9</code></td></tr>
<tr><td>LoongArch</td><td><code>$r[23-31]</code></td><td><code>$s[0-8]</code></td></tr>
<tr><td>LoongArch</td><td><code>$f[0-7]</code></td><td><code>$fa[0-7]</code></td></tr>
<tr><td>LoongArch</td><td><code>$f[8-23]</code></td><td><code>$ft[0-15]</code></td></tr>
<tr><td>LoongArch</td><td><code>$f[24-31]</code></td><td><code>$fs[0-7]</code></td></tr>
</tbody></table>
</div><div class="rule" id="asm.register-names.not-for-io"><a class="rule-link" href="#asm.register-names.not-for-io">[asm.register-names.not-for-io]</a></div>
<p>某些寄存器不能用于输入或输出操作：</p>
<div class="table-wrapper"><table><thead><tr><th>体系架构</th><th>不支持的寄存器</th><th>原因</th></tr></thead><tbody>
<tr><td>All</td><td><code>sp</code></td><td>栈指针必须在 asm代码块末尾恢复为其原始值。</td></tr>
<tr><td>All</td><td><code>bp</code> (x86), <code>x29</code> (AArch64), <code>x8</code> (RISC-V), <code>$fp</code> (LoongArch)</td><td>帧指针不能用作输入或输出。</td></tr>
<tr><td>ARM</td><td><code>r7</code> or <code>r11</code></td><td>在 ARM 上，帧指针可以是 <code>r7</code> 或 <code>r11</code>，具体取决于目标架构。帧指针不能用作输入或输出。</td></tr>
<tr><td>All</td><td><code>si</code> (x86-32), <code>bx</code> (x86-64), <code>r6</code> (ARM), <code>x19</code> (AArch64), <code>x9</code> (RISC-V), <code>$s8</code> (LoongArch)</td><td>LLVM 在内部将其用作具有复杂栈帧的函数的“基指针”。</td></tr>
<tr><td>x86</td><td><code>ip</code></td><td>这是程序计数器，不是真正的寄存器。</td></tr>
<tr><td>AArch64</td><td><code>xzr</code></td><td>这是一个不能修改的常量零寄存器。</td></tr>
<tr><td>AArch64</td><td><code>x18</code></td><td>这是一些 AArch64目标架构上的操作系统预留寄存器。</td></tr>
<tr><td>ARM</td><td><code>pc</code></td><td>这是程序计数器，不是真正的寄存器。</td></tr>
<tr><td>ARM</td><td><code>r9</code></td><td>这是一些 ARM目标架构上的操作系统预留寄存器。</td></tr>
<tr><td>RISC-V</td><td><code>x0</code></td><td>这是一个不能修改的常量零寄存器。</td></tr>
<tr><td>RISC-V</td><td><code>gp</code>, <code>tp</code></td><td>这些寄存器是预留的，不能用作输入或输出。</td></tr>
<tr><td>LoongArch</td><td><code>$r0</code> or <code>$zero</code></td><td>这是一个不能修改的常量零寄存器。</td></tr>
<tr><td>LoongArch</td><td><code>$r2</code> or <code>$tp</code></td><td>这是为TLS保留的。</td></tr>
<tr><td>LoongArch</td><td><code>$r21</code></td><td>这是 ABI 所保留的。</td></tr>
</tbody></table>
</div><div class="rule" id="asm.register-names.fp-bp-reserved"><a class="rule-link" href="#asm.register-names.fp-bp-reserved">[asm.register-names.fp-bp-reserved]</a></div>
<p>帧指针和基指针寄存器(base pointer register)预留供 LLVM 内部使用。而 <code>asm!</code>语句不能显式去指定使用预留寄存器，但在某些情况下，LLVM 将为 <code>reg</code>操作分配其中一个预留寄存器。使用预留寄存器的汇编代码应该小心，因为 <code>reg</code>操作可能在使用相同的寄存器。</p>
<h2 id="template-modifiers"><a class="header" href="#template-modifiers">Template modifiers</a></h2>
<h2 id="模板修饰符"><a class="header" href="#模板修饰符">模板修饰符</a></h2>
<div class="rule" id="asm.template-modifiers"><a class="rule-link" href="#asm.template-modifiers">[asm.template-modifiers]</a></div>
<div class="rule" id="asm.template-modifiers.intro"><a class="rule-link" href="#asm.template-modifiers.intro">[asm.template-modifiers.intro]</a></div>
<p>占位符可以通过在大括号中的 <code>:</code> 之后指定的修饰符进行扩充。
这些修饰符不影响寄存器分配，但会更改插入模板字符串时操作(operand)的格式化方式。</p>
<div class="rule" id="asm.template-modifiers.only-one"><a class="rule-link" href="#asm.template-modifiers.only-one">[asm.template-modifiers.only-one]</a></div>
<p>每个模板占位符只允许一个修饰符。</p>
<div class="rule" id="asm.template-modifiers.supported-modifiers"><a class="rule-link" href="#asm.template-modifiers.supported-modifiers">[asm.template-modifiers.supported-modifiers]</a></div>
<p>支持的修饰符是 LLVM（和 GCC）<a href="http://llvm.org/docs/LangRef.html#asm-template-argument-modifiers">asm模板参数修饰符</a>的子集，但不使用相同的字母代码。</p>
<div class="table-wrapper"><table><thead><tr><th>体系架构</th><th>寄存器类</th><th>修饰符</th><th>输出示例</th><th>LLVM修饰符</th></tr></thead><tbody>
<tr><td>x86-32</td><td><code>reg</code></td><td>None</td><td><code>eax</code></td><td><code>k</code></td></tr>
<tr><td>x86-64</td><td><code>reg</code></td><td>None</td><td><code>rax</code></td><td><code>q</code></td></tr>
<tr><td>x86-32</td><td><code>reg_abcd</code></td><td><code>l</code></td><td><code>al</code></td><td><code>b</code></td></tr>
<tr><td>x86-64</td><td><code>reg</code></td><td><code>l</code></td><td><code>al</code></td><td><code>b</code></td></tr>
<tr><td>x86</td><td><code>reg_abcd</code></td><td><code>h</code></td><td><code>ah</code></td><td><code>h</code></td></tr>
<tr><td>x86</td><td><code>reg</code></td><td><code>x</code></td><td><code>ax</code></td><td><code>w</code></td></tr>
<tr><td>x86</td><td><code>reg</code></td><td><code>e</code></td><td><code>eax</code></td><td><code>k</code></td></tr>
<tr><td>x86-64</td><td><code>reg</code></td><td><code>r</code></td><td><code>rax</code></td><td><code>q</code></td></tr>
<tr><td>x86</td><td><code>reg_byte</code></td><td>None</td><td><code>al</code> / <code>ah</code></td><td>None</td></tr>
<tr><td>x86</td><td><code>xmm_reg</code></td><td>None</td><td><code>xmm0</code></td><td><code>x</code></td></tr>
<tr><td>x86</td><td><code>ymm_reg</code></td><td>None</td><td><code>ymm0</code></td><td><code>t</code></td></tr>
<tr><td>x86</td><td><code>zmm_reg</code></td><td>None</td><td><code>zmm0</code></td><td><code>g</code></td></tr>
<tr><td>x86</td><td><code>*mm_reg</code></td><td><code>x</code></td><td><code>xmm0</code></td><td><code>x</code></td></tr>
<tr><td>x86</td><td><code>*mm_reg</code></td><td><code>y</code></td><td><code>ymm0</code></td><td><code>t</code></td></tr>
<tr><td>x86</td><td><code>*mm_reg</code></td><td><code>z</code></td><td><code>zmm0</code></td><td><code>g</code></td></tr>
<tr><td>x86</td><td><code>kreg</code></td><td>None</td><td><code>k1</code></td><td>None</td></tr>
<tr><td>AArch64</td><td><code>reg</code></td><td>None</td><td><code>x0</code></td><td><code>x</code></td></tr>
<tr><td>AArch64</td><td><code>reg</code></td><td><code>w</code></td><td><code>w0</code></td><td><code>w</code></td></tr>
<tr><td>AArch64</td><td><code>reg</code></td><td><code>x</code></td><td><code>x0</code></td><td><code>x</code></td></tr>
<tr><td>AArch64</td><td><code>vreg</code></td><td>None</td><td><code>v0</code></td><td>None</td></tr>
<tr><td>AArch64</td><td><code>vreg</code></td><td><code>v</code></td><td><code>v0</code></td><td>None</td></tr>
<tr><td>AArch64</td><td><code>vreg</code></td><td><code>b</code></td><td><code>b0</code></td><td><code>b</code></td></tr>
<tr><td>AArch64</td><td><code>vreg</code></td><td><code>h</code></td><td><code>h0</code></td><td><code>h</code></td></tr>
<tr><td>AArch64</td><td><code>vreg</code></td><td><code>s</code></td><td><code>s0</code></td><td><code>s</code></td></tr>
<tr><td>AArch64</td><td><code>vreg</code></td><td><code>d</code></td><td><code>d0</code></td><td><code>d</code></td></tr>
<tr><td>AArch64</td><td><code>vreg</code></td><td><code>q</code></td><td><code>q0</code></td><td><code>q</code></td></tr>
<tr><td>ARM</td><td><code>reg</code></td><td>None</td><td><code>r0</code></td><td>None</td></tr>
<tr><td>ARM</td><td><code>sreg</code></td><td>None</td><td><code>s0</code></td><td>None</td></tr>
<tr><td>ARM</td><td><code>dreg</code></td><td>None</td><td><code>d0</code></td><td><code>P</code></td></tr>
<tr><td>ARM</td><td><code>qreg</code></td><td>None</td><td><code>q0</code></td><td><code>q</code></td></tr>
<tr><td>ARM</td><td><code>qreg</code></td><td><code>e</code> / <code>f</code></td><td><code>d0</code> / <code>d1</code></td><td><code>e</code> / <code>f</code></td></tr>
<tr><td>RISC-V</td><td><code>reg</code></td><td>None</td><td><code>x1</code></td><td>None</td></tr>
<tr><td>RISC-V</td><td><code>freg</code></td><td>None</td><td><code>f0</code></td><td>None</td></tr>
<tr><td>LoongArch</td><td><code>reg</code></td><td>None</td><td><code>$r1</code></td><td>None</td></tr>
<tr><td>LoongArch</td><td><code>freg</code></td><td>None</td><td><code>$f0</code></td><td>None</td></tr>
</tbody></table>
</div>
<blockquote>
<p><strong>注意</strong>:</p>
<ul>
<li>对于 ARM架构 <code>e</code> / <code>f</code>: 这将打印出 NEON quad（128位）寄存器的低双字或高双字寄存器名称。</li>
<li>对于 x86架构: 对于没有修饰符的 <code>reg</code>，Rust 编译器与 GCC 的编译行为不同。
GCC 将根据操作值的类型推断修饰符，而 Rust 默认为完整寄存器宽度。</li>
<li>对于 x86架构的 <code>xmm_reg</code>: LLVM修饰符 <code>x</code>、<code>t</code> 和 <code>g</code> 目前还未在 LLVM 中真正实现(目前它们仅被 GCC 支持)，但这应该将只是一个小变动。</li>
</ul>
</blockquote>
<div class="rule" id="asm.template-modifiers.smaller-value"><a class="rule-link" href="#asm.template-modifiers.smaller-value">[asm.template-modifiers.smaller-value]</a></div>
<p>如前一节开头所述，传递小于寄存器宽度的输入值将导致寄存器的高位包含未定义的值。
如果内联asm 仅访问寄存器的低位，则这不是问题，这可以通过使用模板修饰符在 asm代码中使用子寄存器名称（例如，使用 <code>ax</code> 替代 <code>rax</code>）来实现。
由于这是一个容易犯的错误，编译器将建议在适当的情况下使用模板修饰符来给出输入值的类型。
但如果某个操作的所有引用都已包含了修饰符，则对该操作的警告将会被抑制。</p>
<h2 id="abi-clobbers"><a class="header" href="#abi-clobbers">ABI clobbers</a></h2>
<div class="rule" id="asm.abi-clobbers"><a class="rule-link" href="#asm.abi-clobbers">[asm.abi-clobbers]</a></div>
<div class="rule" id="asm.abi-clobbers.intro"><a class="rule-link" href="#asm.abi-clobbers.intro">[asm.abi-clobbers.intro]</a></div>
<p>关键字<code>clobber_abi</code> 可用于将与之对应的一组默认的 clobber寄存器应用于 <code>asm!</code>块内。
这在调用具有特定调用约定的函数时，会根据需要自动插入必要的 clobber约束：如果调用约定没有在调用过程中完整保持寄存器的值，则会将 <code>lateout("...") _</code> 隐式添加到操作列表中 (其中 <code>...</code> 要用具体的寄存器名字替换掉)。</p>
<div class="rule" id="asm.abi-clobbers.many"><a class="rule-link" href="#asm.abi-clobbers.many">[asm.abi-clobbers.many]</a></div>
<p><code>clobber_abi</code> 可以指定任意多次。它将为所有指定了调用约定的寄存器集合中的所有单一寄存器都分配一个 clobber寄存器。</p>
<div class="rule" id="asm.abi-clobbers.must-specify"><a class="rule-link" href="#asm.abi-clobbers.must-specify">[asm.abi-clobbers.must-specify]</a></div>
<p>当使用 <code>clobber_abi</code> 时，不允许把通用寄存器类作为输出寄存器类来指定：此时所有输出寄存器必须显式指定。</p>
<div class="rule" id="asm.abi-clobbers.explicit-have-precedence"><a class="rule-link" href="#asm.abi-clobbers.explicit-have-precedence">[asm.abi-clobbers.explicit-have-precedence]</a></div>
<p>有 <code>clobber_abi</code> 时，把显式输出寄存器标记为输出寄存器的工作优先于给寄存器隐式插入 clobber标志：此时只有当该寄存器明确未用作输出时，才会为寄存器插入 clobber标记。</p>
<div class="rule" id="asm.abi-clobbers.supported-abis"><a class="rule-link" href="#asm.abi-clobbers.supported-abis">[asm.abi-clobbers.supported-abis]</a></div>
<p>以下的 ABI 可与 <code>clobber_abi</code> 一起使用：</p>
<div class="table-wrapper"><table><thead><tr><th>体系架构</th><th>ABI名称</th><th>Clobbered寄存器</th></tr></thead><tbody>
<tr><td>x86-32</td><td><code>"C"</code>, <code>"system"</code>, <code>"efiapi"</code>, <code>"cdecl"</code>, <code>"stdcall"</code>, <code>"fastcall"</code></td><td><code>ax</code>, <code>cx</code>, <code>dx</code>, <code>xmm[0-7]</code>, <code>mm[0-7]</code>, <code>k[1-7]</code>, <code>st([0-7])</code></td></tr>
<tr><td>x86-64</td><td><code>"C"</code>, <code>"system"</code> (Windows平台), <code>"efiapi"</code>, <code>"win64"</code></td><td><code>ax</code>, <code>cx</code>, <code>dx</code>, <code>r[8-11]</code>, <code>xmm[0-31]</code>, <code>mm[0-7]</code>, <code>k[1-7]</code>, <code>st([0-7])</code>, <code>tmm[0-7]</code></td></tr>
<tr><td>x86-64</td><td><code>"C"</code>, <code>"system"</code> (在非Windows平台上), <code>"sysv64"</code></td><td><code>ax</code>, <code>cx</code>, <code>dx</code>, <code>si</code>, <code>di</code>, <code>r[8-11]</code>, <code>xmm[0-31]</code>, <code>mm[0-7]</code>, <code>k[1-7]</code>, <code>st([0-7])</code>, <code>tmm[0-7]</code></td></tr>
<tr><td>AArch64</td><td><code>"C"</code>, <code>"system"</code>, <code>"efiapi"</code></td><td><code>x[0-17]</code>, <code>x18</code>*, <code>x30</code>, <code>v[0-31]</code>, <code>p[0-15]</code>, <code>ffr</code></td></tr>
<tr><td>ARM</td><td><code>"C"</code>, <code>"system"</code>, <code>"efiapi"</code>, <code>"aapcs"</code></td><td><code>r[0-3]</code>, <code>r12</code>, <code>r14</code>, <code>s[0-15]</code>, <code>d[0-7]</code>, <code>d[16-31]</code></td></tr>
<tr><td>RISC-V</td><td><code>"C"</code>, <code>"system"</code>, <code>"efiapi"</code></td><td><code>x1</code>, <code>x[5-7]</code>, <code>x[10-17]</code>, <code>x[28-31]</code>, <code>f[0-7]</code>, <code>f[10-17]</code>, <code>f[28-31]</code>, <code>v[0-31]</code></td></tr>
<tr><td>LoongArch</td><td><code>"C"</code>, <code>"system"</code>, <code>"efiapi"</code></td><td><code>$r1</code>, <code>$r[4-20]</code>, <code>$f[0-23]</code></td></tr>
</tbody></table>
</div>
<blockquote>
<p>注意：</p>
<ul>
<li>在 AArch64架构上，如果 <code>x18</code> 不是目标架构上的预留寄存器，则它仅被包括在 clobber寄存器列表中。</li>
</ul>
</blockquote>
<p>随着体系架构中新的寄存器的加入，在rustc中，每个 ABI 对应的 clobbered寄存器列表也会一并更新：这确保了当 LLVM 开始在其生成的代码中使用这些新寄存器时，<code>asm!</code> 里的 clobber寄存器的正确性也能得到保持。</p>
<h2 id="options"><a class="header" href="#options">Options</a></h2>
<h2 id="可选项"><a class="header" href="#可选项">可选项</a></h2>
<div class="rule" id="asm.options"><a class="rule-link" href="#asm.options">[asm.options]</a></div>
<div class="rule" id="asm.options.supported-options"><a class="rule-link" href="#asm.options.supported-options">[asm.options.supported-options]</a></div>
<p>我们使用标志（Flag）技术来进一步影响内联汇编块的行为。
目前定义了以下可选项（标志）：</p>
<div class="rule" id="asm.options.supported-options.pure"><a class="rule-link" href="#asm.options.supported-options.pure">[asm.options.supported-options.pure]</a></div>
<ul>
<li><code>pure</code>：此 <code>asm!</code>块没有副作用，且最终必须返回，其输出仅取决于其直接输入（比如，输入的值本身，而不是它们指向的对象）或从内存读取的值（除非还设置了 <code>nomem</code>可选项）。
这允许编译器执行此 <code>asm!</code>块的次数少于程序中指定的次数（例如，通过将其从循环中提出来），或者如果 <code>asm!</code>块没有输出的情况下，编译器甚至可能完全消除此段 asm代码。
<code>pure</code>可选项必须与 <code>nomem</code> 或 <code>readonly</code> 可选项组合使用，否则会导致编译期错误。</li>
</ul>
<div class="rule" id="asm.options.supported-options.nomem"><a class="rule-link" href="#asm.options.supported-options.nomem">[asm.options.supported-options.nomem]</a></div>
<ul>
<li><code>nomem</code>：此 <code>asm!</code>块不读取或写入任何内存。
这允许编译器将修改过的全局变量的值缓存在跨当前 <code>asm!</code>块的寄存器中，因为它知道当前 <code>asm!</code>不会读取或写入它们。
编译器还假定此 <code>asm!</code>块不执行与其他线程的任何类型的同步，例如通过 fence。</li>
</ul>
<div class="rule" id="asm.options.supported-options.readonly"><a class="rule-link" href="#asm.options.supported-options.readonly">[asm.options.supported-options.readonly]</a></div>
<ul>
<li><code>readonly</code>：此 <code>asm!</code>块不写入任何内存。
这允许编译器将未修改的全局变量的值缓存在跨当前 <code>asm!</code>块的寄存器中，因为它知道它们不是由当前 <code>asm!</code>写入的。
编译器还假定此 <code>asm!</code>块不执行与其他线程的任何类型的同步，例如通过 fence。</li>
</ul>
<div class="rule" id="asm.options.supported-options.preserves_flags"><a class="rule-link" href="#asm.options.supported-options.preserves_flags">[asm.options.supported-options.preserves_flags]</a></div>
<ul>
<li><code>preserves_flags</code>：此 <code>asm！</code>块不修改标志寄存器（在后面章节的规则表中有定义）。
这可以避免编译器在此 <code>asm!</code>块之后重新计算条件标志。</li>
</ul>
<div class="rule" id="asm.options.supported-options.noreturn"><a class="rule-link" href="#asm.options.supported-options.noreturn">[asm.options.supported-options.noreturn]</a></div>
<ul>
<li><code>noreturn</code>：此 <code>asm!</code>块没有具体返回值，其返回类型被定义为 <code>!</code>(never)。
如果执行超过 asm代码的末尾，则为未定义行为。(译者注：asm代码末尾应该有跳转，否则执行程序会顺序执行二进制指令，从而执行超出 asm代码块)
有 <code>noreturn</code>可选项的 asm块的行为就像一个不返回的函数；需要注意的是，其作用域中的局部变量在被调用之前不会被销毁。</li>
</ul>
<div class="rule" id="asm.options.supported-options.nostack"><a class="rule-link" href="#asm.options.supported-options.nostack">[asm.options.supported-options.nostack]</a></div>
<ul>
<li><code>nostack</code>：此 <code>asm！</code>块不会将数据推送到栈上，也不会写入栈的红色区域（red-zone）（有些目标架构会支持red-zone）。
如果此可选项<em>未</em>使用，则保证栈指针为函数调用会（根据目标ABI）适当对齐。</li>
</ul>
<div class="rule" id="asm.options.supported-options.att_syntax"><a class="rule-link" href="#asm.options.supported-options.att_syntax">[asm.options.supported-options.att_syntax]</a></div>
<ul>
<li><code>att_syntax</code>：此可选项仅在 x86架构上有效，并导致汇编器使用 GNU汇编器的 <code>.att_syntax prefix</code>模式。
寄存器操作在被替换时会自动加上前导<code>%</code>。</li>
</ul>
<div class="rule" id="asm.options.supported-options.raw"><a class="rule-link" href="#asm.options.supported-options.raw">[asm.options.supported-options.raw]</a></div>
<ul>
<li><code>raw</code>：这将导致模板字符串被解析为裸汇编字符串，对 <code>{</code> 和 <code>}</code> 也不做特殊处理。
这在使用 <code>include_str!</code> 从外部文件中包含裸汇编代码时非常有用。</li>
</ul>
<div class="rule" id="asm.options.checks"><a class="rule-link" href="#asm.options.checks">[asm.options.checks]</a></div>
<p>编译器对可选项执行一些附加检查：</p>
<div class="rule" id="asm.options.checks.mutually-exclusive"><a class="rule-link" href="#asm.options.checks.mutually-exclusive">[asm.options.checks.mutually-exclusive]</a></div>
<ul>
<li><code>nomem</code> 和 <code>readonly</code> 是互斥的：同时指定这两个选项会导致编译期错误。</li>
</ul>
<div class="rule" id="asm.options.checks.pure"><a class="rule-link" href="#asm.options.checks.pure">[asm.options.checks.pure]</a></div>
<ul>
<li>在没有输出或只有丢弃的输出(<code>_</code>)的 asm块上指定 <code>pure</code> 会导致编译期错误。</li>
</ul>
<div class="rule" id="asm.options.checks.noreturn"><a class="rule-link" href="#asm.options.checks.noreturn">[asm.options.checks.noreturn]</a></div>
<ul>
<li>在带有输出的 asm块上指定 <code>noreturn</code> 会导致编译期错误。</li>
</ul>
<div class="rule" id="asm.options.global_asm-restriction"><a class="rule-link" href="#asm.options.global_asm-restriction">[asm.options.global_asm-restriction]</a></div>
<p><code>global_asm!</code> 仅支持 <code>att_syntax</code> 和 <code>raw</code> 可选项。
其余可选项对于全局作用域类型的内联汇编没有意义。</p>
<h2 id="rules-for-inline-assembly"><a class="header" href="#rules-for-inline-assembly">Rules for inline assembly</a></h2>
<h2 id="内联汇编规则"><a class="header" href="#内联汇编规则">内联汇编规则</a></h2>
<div class="rule" id="asm.rules"><a class="rule-link" href="#asm.rules">[asm.rules]</a></div>
<div class="rule" id="asm.rules.intro"><a class="rule-link" href="#asm.rules.intro">[asm.rules.intro]</a></div>
<p>为了避免未定义行为，在使用函数作用域类型的内联汇编（<code>asm!</code>）时必须遵循以下规则：</p>
<div class="rule" id="asm.rules.reg-not-input"><a class="rule-link" href="#asm.rules.reg-not-input">[asm.rules.reg-not-input]</a></div>
<ul>
<li>任何未指定为输入的寄存器在进入 asm块时都会包含未定义的值。
<ul>
<li>内联汇编上下文中的“未定义值”意味着寄存器可以（非确定性地）具有体系架构允许的任何一个可能值。
值得注意的是，它与 LLVM 的 <code>undef</code> 不同，LLVM 的 <code>undef</code> 每次读取时都会有不同的值（因为在汇编代码中不存在这样的概念）。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.reg-not-output"><a class="rule-link" href="#asm.rules.reg-not-output">[asm.rules.reg-not-output]</a></div>
<ul>
<li>任何未指定为输出的寄存器在退出 asm块时必须具有与进入时相同的值，否则为未定义行为。
<ul>
<li>这仅适用于可指定为输入或输出的寄存器。
其他寄存器遵循特定于目标架构的规则。</li>
<li>请注意，<code>lateout</code> 可以分配给与 <code>in</code> 相同的寄存器，在这种情况下，此规则不适用。
然而，代码不应该依赖于此，因为它依赖于寄存器分配的结果。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.unwind"><a class="rule-link" href="#asm.rules.unwind">[asm.rules.unwind]</a></div>
<ul>
<li>如果在 asm块中执行展开（unwind），则为未定义行为。
<ul>
<li>如果汇编代码调用一个函数，然后该函数展开，则这也适用此规则。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.mem-same-as-ffi"><a class="rule-link" href="#asm.rules.mem-same-as-ffi">[asm.rules.mem-same-as-ffi]</a></div>
<ul>
<li>汇编代码允许读取和写入的内存位置集与 FFI函数允许读取和写入的内存位置集相同。
<ul>
<li>有关确切规则，请参阅不安全代码指南。</li>
<li>如果设置了 <code>readonly</code>可选项，则只允许内存读取。</li>
<li>如果设置了 <code>nomem</code>可选项，则不允许对内存进行读取或写入。</li>
<li>这些规则不适用于 asm代码私有的内存空间，例如 asm块内分配的堆栈空间。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.black-box"><a class="rule-link" href="#asm.rules.black-box">[asm.rules.black-box]</a></div>
<ul>
<li>编译器不能假定 asm块中的指令是最终实际执行的指令。
<ul>
<li>这实际上意味着编译器必须将 <code>asm!</code> 作为一个黑盒对待，只考虑接口规范，而不考虑 asm块内的指令本身。</li>
<li>允许通过特定于目标架构的机制来执行运行时代码补丁。</li>
<li>然而，不能保证每个 <code>asm！</code>直接对应于目标文件中指令的单个实例：编译器可以自由复制或消除重复的 <code>asm！</code>块。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.stack-below-sp"><a class="rule-link" href="#asm.rules.stack-below-sp">[asm.rules.stack-below-sp]</a></div>
<ul>
<li>除非设置了 <code>nostack</code>可选项，否则可以允许 asm代码使用栈指针下方的栈空间。
<ul>
<li>当进入 asm块后，为保证栈指针为函数调用，此指针会（根据目标ABI）适当对齐。</li>
<li>你有责任确保不会溢出堆栈（例如，使用堆栈探测以确保命中保护页）。</li>
<li>根据目标ABI的要求分配堆栈内存时，应调整堆栈指针。</li>
<li>在离开 asm块之前，必须将堆栈指针还原为其原始值。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.noreturn"><a class="rule-link" href="#asm.rules.noreturn">[asm.rules.noreturn]</a></div>
<ul>
<li>如果设置了 <code>noreturn</code>可选项，则如果执行超过 asm块的末尾，则此行为未定义。</li>
</ul>
<div class="rule" id="asm.rules.pure"><a class="rule-link" href="#asm.rules.pure">[asm.rules.pure]</a></div>
<ul>
<li>如果设置了 <code>pure</code>可选项，那么如果 <code>asm!</code>代码除了有直接输出外，还有其他副作用，则此行为未定义。
如果两次执行 <code>asm!</code>代码，它们具有相同输入，但输出不同，此行为也未定义。
<ul>
<li>当与 <code>nomem</code>可选项一起使用时，所谓的“输入”只能是 <code>asm!</code>的直接输入。</li>
<li>当与 <code>readonly</code>可选项一起使用时，所谓的“输入”包含 <code>asm!</code>的直接输入，还包含允许 <code>asm!</code>块来读取的全部内存。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.preserved-registers"><a class="rule-link" href="#asm.rules.preserved-registers">[asm.rules.preserved-registers]</a></div>
<ul>
<li>如果设置了 <code>preserves_flags</code>可选项，则在退出 asm块时必须恢复这些标志寄存器：
<ul>
<li>x86
<ul>
<li><code>EFLAGS</code> (CF, PF, AF, ZF, SF, OF)中的状态标志寄存器。</li>
<li>浮点状态字 (全部)。</li>
<li><code>MXCSR</code> (PE, UE, OE, ZE, DE, IE)中的浮点异常标志寄存器。</li>
</ul>
</li>
<li>ARM
<ul>
<li><code>CPSR</code> (N, Z, C, V)中的条件标志寄存器。</li>
<li><code>CPSR</code> (Q)中的饱和标志寄存器。</li>
<li><code>CPSR</code> (GE)中的大于或等于标志寄存器。</li>
<li><code>FPSCR</code> (N, Z, C, V)中的条件标志寄存器。</li>
<li><code>FPSCR</code> (QC)中的饱和标志寄存器。</li>
<li><code>FPSCR</code> (IDC, IXC, UFC, OFC, DZC, IOC)中的浮点异常标志寄存器。</li>
</ul>
</li>
<li>AArch64
<ul>
<li>条件标志寄存器(<code>NZCV</code>)。</li>
<li>浮点状态寄存器(<code>FPSR</code>).</li>
</ul>
</li>
<li>RISC-V
<ul>
<li><code>fcsr</code> (<code>fflags</code>)中的浮点异常标志寄存器。</li>
<li>向量扩展状态寄存器(<code>vtype</code>, <code>vl</code>, <code>vcsr</code>)。</li>
</ul>
</li>
<li>LoongArch
<ul>
<li><code>$fcc[0-7]</code> 中的浮点条件标志寄存器。</li>
</ul>
</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.x86-df"><a class="rule-link" href="#asm.rules.x86-df">[asm.rules.x86-df]</a></div>
<ul>
<li>在 x86 上，方向标志寄存器（<code>EFLAGS</code> 中的 DF）在进入 asm块时清除，在退出时也必须清除。
<ul>
<li>如果在退出 asm块时设置了方向标志，则此行为未定义。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.x86-x87"><a class="rule-link" href="#asm.rules.x86-x87">[asm.rules.x86-x87]</a></div>
<ul>
<li>在 x86 上，x87浮点寄存器栈必须保持不变，除非所有的 <code>st([0-7])</code>寄存器都被用 <code>out("st(0)") _, out("st(1)") _, ...</code>标记标记为 clobber寄存器。
<ul>
<li>如果所有 x87寄存器都被标记为 clobber寄存器，则在进入 <code>asm</code>块时，x87寄存器栈被保证为空。并且汇编代码必须确保退出 asm块时 x87寄存器栈也为空。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.only-on-exit"><a class="rule-link" href="#asm.rules.only-on-exit">[asm.rules.only-on-exit]</a></div>
<ul>
<li>将堆栈指针和非输出寄存器恢复为其原始值的要求仅在退出 <code>asm!</code>块时适用。
<ul>
<li>这意味着永不返回的 <code>asm!</code>块（即使未标记为 <code>noreturn</code>）不需要恢复这些寄存器。</li>
<li>当返回到其他的 <code>asm!</code>块（例如上下文切换）时，这些寄存器必须包含它们在进入当前（你正在<em>退出</em>）的 <code>asm!</code>块的值。
<ul>
<li>你不能退出尚未进入的 <code>asm!</code>块。
你也不能退出已退出的 <code>asm!</code>块（也可以理解为不能未进入而退出）。</li>
<li>你负责切换任何特定于目标架构的状态（例如线程级的本地存储和堆栈边界）。</li>
<li>你不能从一个 <code>asm!</code>块中的地址跳转块到另一个 <code>asm!</code>块中的地址，即使在同一个函数或块中也不行。应将两个 <code>asm!</code>块的上下文视为潜在不同，跳转时会进行上下文切换。  你不能假设这些上下文中的任何特定值（例如当前堆栈指针或堆栈指针下的临时值）在两个 <code>asm!</code>块之间保持不变。</li>
<li>你可以访问的内存位置集是你进入的 <code>asm!</code>块所允许的内存位置和你刚退出的 <code>asm!</code>块所允许的内存位置的交集。</li>
</ul>
</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.not-successive"><a class="rule-link" href="#asm.rules.not-successive">[asm.rules.not-successive]</a></div>
<ul>
<li>即使两个 <code>asm!</code>块在源代码中相邻，并且它们之间没有任何其他代码，你仍不能假设它们也将在二进制中的地址连续，不能保证它们之间没有任何其他指令。</li>
</ul>
<div class="rule" id="asm.rules.not-exactly-once"><a class="rule-link" href="#asm.rules.not-exactly-once">[asm.rules.not-exactly-once]</a></div>
<ul>
<li>你不能假设 <code>asm!</code>块在输出的二进制文件中只出现一次。
允许编译器实例化 <code>asm!</code>块的多个副本块，例如当包含它的函数在多个位置内联时。</li>
</ul>
<div class="rule" id="asm.rules.x86-prefix-restriction"><a class="rule-link" href="#asm.rules.x86-prefix-restriction">[asm.rules.x86-prefix-restriction]</a></div>
<ul>
<li>在 x86 上，内联汇编不能以指令前缀（如 <code>LOCK</code>）结尾（这些指令前缀被用于编译器生成的指令）。
<ul>
<li>由于内联汇编的编译方式，编译器当前还无法检测到此问题，但将来可能会捕获并拒绝此问题。</li>
</ul>
</li>
</ul>
<div class="rule" id="asm.rules.preserves_flags"><a class="rule-link" href="#asm.rules.preserves_flags">[asm.rules.preserves_flags]</a></div>
<blockquote>
<p><strong>注意</strong>：作为一个一般性原则，<code>preserves_flags</code> 包含的标志是在执行函数调用时<em>未</em>保留的标志。</p>
</blockquote>
<h3 id="correctness-and-validity"><a class="header" href="#correctness-and-validity">Correctness and Validity</a></h3>
<h3 id="正确性和有效性"><a class="header" href="#正确性和有效性">正确性和有效性</a></h3>
<div class="rule" id="asm.validity"><a class="rule-link" href="#asm.validity">[asm.validity]</a></div>
<div class="rule" id="asm.validity.necessary-but-not-sufficient"><a class="rule-link" href="#asm.validity.necessary-but-not-sufficient">[asm.validity.necessary-but-not-sufficient]</a></div>
<p>除了前面的所有规则外，<code>asm!</code> 的字符串参数（在计算完所有其他参数后，执行格式化并转换其操作数）必须最终转换成为（对于目标体系结构而言）语法正确且语义有效的汇编代码。
其中，格式化规则允许编译器生成具有正确语法的汇编代码。
有关操作数的规则允许将 Rust操作数有效转换为<code>asm!</code>，以及从 <code>asm!</code> 转换出。
为使最终汇编代码既正确又有效，遵守这些规则是必要的，但还不够。例如：</p>
<ul>
<li>格式化后，参数可能被放置在语法不正确的位置</li>
<li>一条指令可能被正确写入，但该操作数在给定的体系结构上却是无效的</li>
<li>对应体系结构未支持的指令可以汇编成不确定的代码</li>
<li>一组指令，每一条都正确有效，如果连续放置，仍有可能会导致未定义的行为</li>
</ul>
<div class="rule" id="asm.validity.non-exhaustive"><a class="rule-link" href="#asm.validity.non-exhaustive">[asm.validity.non-exhaustive]</a></div>
<p>因此，这些规则是 <em>非穷尽</em> 的。编译器不需要检查初始字符串的正确性和有效性，也不需要检查生成的最终汇编代码。
汇编器可以检查这些代码的正确性和有效性，但不需要这样做。
使用 <code>asm!</code> 时，键入错误就足以使程序变得不健壮。完全排除这类错误太难了，汇编规则那是包含在数千页的体系结构参考手册中的呀。
程序员应该谨慎行事，调用这种 <code>unsafe</code> 的功能需要承担不违反编译器或体系结构规则的责任。</p>
<h3 id="directives-support"><a class="header" href="#directives-support">Directives Support</a></h3>
<h3 id="伪指令支持"><a class="header" href="#伪指令支持">伪指令支持</a></h3>
<div class="rule" id="asm.directives"><a class="rule-link" href="#asm.directives">[asm.directives]</a></div>
<div class="rule" id="asm.directives.subset-supported"><a class="rule-link" href="#asm.directives.subset-supported">[asm.directives.subset-supported]</a></div>
<p>内联汇编支持 GNU AS 和 LLVM 的内部汇编器支持的伪指令集的一个子集，具体如下所示。
也有部分伪指令的效果是特定于汇编器的（可能会导致错误，或者可能会被接受）。</p>
<div class="rule" id="asm.directives.stateful"><a class="rule-link" href="#asm.directives.stateful">[asm.directives.stateful]</a></div>
<p>如果内联汇编包含任何修改后续汇编程序的“有状态(stateful)”伪指令，则块必须在内联汇编结束之前撤消任何此类伪指令的执行效果。</p>
<div class="rule" id="asm.directives.supported-directives"><a class="rule-link" href="#asm.directives.supported-directives">[asm.directives.supported-directives]</a></div>
<p>下面这些伪指令被汇编器确保支持：</p>
<ul>
<li><code>.2byte</code></li>
<li><code>.4byte</code></li>
<li><code>.8byte</code></li>
<li><code>.align</code></li>
<li><code>.alt_entry</code></li>
<li><code>.ascii</code></li>
<li><code>.asciz</code></li>
<li><code>.balign</code></li>
<li><code>.balignl</code></li>
<li><code>.balignw</code></li>
<li><code>.bss</code></li>
<li><code>.byte</code></li>
<li><code>.comm</code></li>
<li><code>.data</code></li>
<li><code>.def</code></li>
<li><code>.double</code></li>
<li><code>.endef</code></li>
<li><code>.equ</code></li>
<li><code>.equiv</code></li>
<li><code>.eqv</code></li>
<li><code>.fill</code></li>
<li><code>.float</code></li>
<li><code>.global</code></li>
<li><code>.globl</code></li>
<li><code>.inst</code></li>
<li><code>.insn</code></li>
<li><code>.lcomm</code></li>
<li><code>.long</code></li>
<li><code>.octa</code></li>
<li><code>.option</code></li>
<li><code>.p2align</code></li>
<li><code>.popsection</code></li>
<li><code>.private_extern</code></li>
<li><code>.pushsection</code></li>
<li><code>.quad</code></li>
<li><code>.scl</code></li>
<li><code>.section</code></li>
<li><code>.set</code></li>
<li><code>.short</code></li>
<li><code>.size</code></li>
<li><code>.skip</code></li>
<li><code>.sleb128</code></li>
<li><code>.space</code></li>
<li><code>.string</code></li>
<li><code>.text</code></li>
<li><code>.type</code></li>
<li><code>.uleb128</code></li>
<li><code>.word</code></li>
</ul>
<h4 id="target-specific-directive-support"><a class="header" href="#target-specific-directive-support">Target Specific Directive Support</a></h4>
<h4 id="基于特定目标规范的指令支持"><a class="header" href="#基于特定目标规范的指令支持">基于特定目标规范的指令支持</a></h4>
<div class="rule" id="asm.target-specific-directives"><a class="rule-link" href="#asm.target-specific-directives">[asm.target-specific-directives]</a></div>
<h5 id="dwarf-unwinding"><a class="header" href="#dwarf-unwinding">Dwarf Unwinding</a></h5>
<h5 id="dwarf展开"><a class="header" href="#dwarf展开">Dwarf展开</a></h5>
<div class="rule" id="asm.target-specific-directives.dwarf-unwinding"><a class="rule-link" href="#asm.target-specific-directives.dwarf-unwinding">[asm.target-specific-directives.dwarf-unwinding]</a></div>
<p>支持 DWARF展开信息的 ELF目标平台支持以下指令：</p>
<ul>
<li><code>.cfi_adjust_cfa_offset</code></li>
<li><code>.cfi_def_cfa</code></li>
<li><code>.cfi_def_cfa_offset</code></li>
<li><code>.cfi_def_cfa_register</code></li>
<li><code>.cfi_endproc</code></li>
<li><code>.cfi_escape</code></li>
<li><code>.cfi_lsda</code></li>
<li><code>.cfi_offset</code></li>
<li><code>.cfi_personality</code></li>
<li><code>.cfi_register</code></li>
<li><code>.cfi_rel_offset</code></li>
<li><code>.cfi_remember_state</code></li>
<li><code>.cfi_restore</code></li>
<li><code>.cfi_restore_state</code></li>
<li><code>.cfi_return_column</code></li>
<li><code>.cfi_same_value</code></li>
<li><code>.cfi_sections</code></li>
<li><code>.cfi_signal_frame</code></li>
<li><code>.cfi_startproc</code></li>
<li><code>.cfi_undefined</code></li>
<li><code>.cfi_window_save</code></li>
</ul>
<h5 id="structured-exception-handling"><a class="header" href="#structured-exception-handling">Structured Exception Handling</a></h5>
<h5 id="结构化异常处理"><a class="header" href="#结构化异常处理">结构化异常处理</a></h5>
<div class="rule" id="asm.target-specific-directives.structured-exception-handling"><a class="rule-link" href="#asm.target-specific-directives.structured-exception-handling">[asm.target-specific-directives.structured-exception-handling]</a></div>
<p>在带有结构化异常处理机制的目标平台上，可以确保下面的这些附加指令得到支持：</p>
<ul>
<li><code>.seh_endproc</code></li>
<li><code>.seh_endprologue</code></li>
<li><code>.seh_proc</code></li>
<li><code>.seh_pushreg</code></li>
<li><code>.seh_savereg</code></li>
<li><code>.seh_setframe</code></li>
<li><code>.seh_stackalloc</code></li>
</ul>
<h5 id="x86-32-bit-and-64-bit"><a class="header" href="#x86-32-bit-and-64-bit">x86 (32-bit and 64-bit)</a></h5>
<h5 id="x86-32位-and-64位"><a class="header" href="#x86-32位-and-64位">x86 (32位 and 64位)</a></h5>
<div class="rule" id="asm.target-specific-directives.x86"><a class="rule-link" href="#asm.target-specific-directives.x86">[asm.target-specific-directives.x86]</a></div>
<p>无论是 32位还是 64位 x86目标平台，可以确保下面的这些附加指令得到支持：</p>
<ul>
<li><code>.nops</code></li>
<li><code>.code16</code></li>
<li><code>.code32</code></li>
<li><code>.code64</code></li>
</ul>
<p>只有在退出汇编块之前将状态重置为默认状态时，才支持使用 <code>.code16</code>、<code>.code32</code> 和 <code>.code64</code> 这些指令。
默认情况下，32位 x86平台使用 <code>.code32</code>，64位 x86平台使用 <code>.code64</code>。</p>
<h5 id="arm-32-bit"><a class="header" href="#arm-32-bit">ARM (32-bit)</a></h5>
<h5 id="arm-32位"><a class="header" href="#arm-32位">ARM (32位)</a></h5>
<div class="rule" id="asm.target-specific-directives.arm-32-bit"><a class="rule-link" href="#asm.target-specific-directives.arm-32-bit">[asm.target-specific-directives.arm-32-bit]</a></div>
<p>ARM目标平台下，可以确保下面的这些附加指令得到支持：</p>
<ul>
<li><code>.even</code></li>
<li><code>.fnstart</code></li>
<li><code>.fnend</code></li>
<li><code>.save</code></li>
<li><code>.movsp</code></li>
<li><code>.code</code></li>
<li><code>.thumb</code></li>
<li><code>.thumb_func</code></li>
</ul>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="linkage.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next prefetch" href="unsafety.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="linkage.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next prefetch" href="unsafety.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>




        <script>
            window.playground_copyable = true;
        </script>


        <script src="elasticlunr.min.js"></script>
        <script src="mark.min.js"></script>
        <script src="searcher.js"></script>

        <script src="clipboard.min.js"></script>
        <script src="highlight.js"></script>
        <script src="book.js"></script>

        <!-- Custom JS scripts -->


    </div>
    </body>
</html>
